#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#define MAXDATA_LEN 8192
typedef struct package {
    char data[MAXDATA_LEN];
    int  len;
} Package;
int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    /**
     * @description:创建一个套接字
     * @param {*} 第一个参数：协议族，第二个参数：协议类型，第三个参数：协议编号
     * @return {*}成功返回套接字文件描述符，失败返回-1；
     */
    if(-1 == sockfd) {
        perror("socket:\n");
        return -1;
    }

    // inter协议族
    int sockopt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
    struct sockaddr_in myaddr;
    //客户端连接的地址信息
    struct sockaddr_in clientaddr;
    size_t             clientaddrsize = sizeof(clientaddr);
    // size_t clientaddrsize ;
    //协议族
    myaddr.sin_family = AF_INET;
    //端口号,用htons函数将它转换为网络字节序
    myaddr.sin_port = htons(7777);
    // ip地址,0表示本机,inet_addr,将ip转换为网络字节序
    myaddr.sin_addr.s_addr = inet_addr("0");
    bzero(&(myaddr.sin_zero), 8);

    if(-1 == bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr)))
    /**
     * @description:绑定套接字，端口号
     * @param
     * {*}第一个参数：套接字，第二个参数：指向sockaddr的指针，第三个参数：sockaddr结构体大小
     * @return {*}0表示绑定成功，-1表示绑定失败
     */
    {
        perror("bind:\n");
        return -1;
    }
    printf("bind success\n");

    if(-1 == listen(sockfd, 5))
    /**
     * @description:监听端口，初始化可连接队列，套接字变为监听套接字
     * @param {*}第一次参数：套接字；第二个参数：等待队列长度
     * @return {*}0表示成功，-1表示失败
     */
    {
        perror("listen:");
        return -1;
    }
    printf("listen success\n");

    socklen_t clientlen = sizeof(clientaddr);
    int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &clientlen);
    /**
     * @description: 连接客户端
     * @param
     * {*}第一个参数：监听套接字，第二个参数：指向sockaddr的指针，第三个参数：sockaddr结构体大小。后两个参数可以置为NULL；
     * @return {*}成功返回一个用于与客户端通信的连接套接字，失败返回-1
     */
    if(-1 == clientfd) {
        perror("accept:");
        return -1;
    }
    printf("%d %d %d\n", clientaddr.sin_addr.s_addr, ntohs(clientaddr.sin_port),
        clientaddrsize);
    printf("%s %d %d\n", inet_ntoa(clientaddr.sin_addr),
        ntohs(clientaddr.sin_port), clientaddrsize);

    memset(&clientaddr, 0, sizeof(clientaddr));
    getpeername(clientfd, (sockaddr*)&clientaddr, (socklen_t*)&clientaddrsize);
    printf("%d %d %d\n", clientaddr.sin_addr.s_addr, ntohs(clientaddr.sin_port),
        clientaddrsize);
    printf("aceept success\n");
    Package pack;
    // pack.data = (char *)calloc(1,11);
    pack.len = 11;
    char buf[256];
    while(1) {
        pack.len = 11;

        strcpy(pack.data, "hello world");
        memset(buf, sizeof(buf), 0);
        int ret = send(clientfd, &pack, sizeof(pack), 0);

        if(-1 == ret) {
            perror("read:");
            // free(pack.data);
            return -1;
        }
        if(0 == ret) break;
        printf("%d\n %s\n", pack.len, pack.data);
        memset(&pack, 0, sizeof(package));
        sleep(1);
    }
    // free(pack.data);
    close(sockfd);
    close(clientfd);
    return 0;
}